package lims.bridge.remoteprint;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.thrift.TException;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;


public class RemotePrintBridge extends Thread{
	Log logger=LogFactory.getLog(getClass());
	long maxIdleInterval=120000;
	boolean stop;

	private RemotePrintBridgeService service; 
	
	public RemotePrintBridge(RemotePrintBridgeService service){
		this.service=service;
	}

	synchronized public boolean getStop(){
		return stop;
	}
	
	synchronized public void setStop(){
		stop=true;
	}

	public void run(){
		long tick=System.currentTimeMillis();
		logger.info("client started");
		while(!getStop()){
			TSocket socket;
			TProtocol protocol;
			try{
				if(service.isKickedOut()){
					logger.info("I'm kicked out,wait 60 seconds to reconnect");						
					service.setKickedOut(false);
					Thread.sleep(60000);
					continue;
				}
				logger.info(String.format("connect to server,id:%s as %s",service.getBridgeId(),service.bridgeRole));
				String[] addr=service.getServerAddress().split(":");
				socket=new TSocket(addr[0],Integer.parseInt(addr[1]));
				socket.open();
				socket.setTimeout(60000);				
				protocol=new TBinaryProtocol(socket);
				protocol.writeByte((byte) 1);
				protocol.writeString(Base64.encodeBase64String(("R:".concat(service.bridgeRole)).getBytes("utf8")));
				protocol.writeByte((byte) 4);
				
				protocol.writeByte((byte) 1);
				protocol.writeString(Base64.encodeBase64String(("B:".concat(service.getBridgeId()).getBytes("utf8"))));
				protocol.writeString(Base64.encodeBase64String(("U:".concat(service.getUid()).getBytes("utf8"))));
				protocol.writeString(Base64.encodeBase64String(("P:".concat(service.getPassword()).getBytes("utf8"))));
				protocol.writeByte((byte) 4);
				socket.flush();				
				boolean loginResult=protocol.readBool();
				if(!loginResult) throw new Exception("login failed");
			}catch(Exception e1){
				if(e1.getMessage()!=null){
					logger.info("error ".concat(e1.getMessage()));			
				}else{
					logger.info("error...");			
				}
				try {
					logger.info("sleep 60s...");
					sleep(60000);
				} catch (InterruptedException e) {
					break;
				}
				logger.info("connect failed");
				continue;
			}
			logger.info("connect successed,bridge registered");
			TProcessor processor=RemotePrintBridgeService.getInstance().getProcessor();			
			try {
				socket.setTimeout((int) maxIdleInterval);
				while(!getStop()&&!service.isKickedOut()){
					if(System.currentTimeMillis()>tick+maxIdleInterval) {
						logger.info("max idle interval exceed, reconnect now...");
						tick=System.currentTimeMillis();
						break;
					}
					try {
						if(!processor.process(protocol,protocol)) {
							logger.info("process failed,reconnect now...");
							break;
						}else{
							tick=System.currentTimeMillis();
							continue;
						}
					} catch (TException e) {
						break;
					}
				}				
			}finally{
				socket.close();				
			}
			logger.info("connect closed");
		}
		logger.info("client finished");
	}
	
}
